using System;

using System.IO;
using Lizk.SimpleHUD;
using System.Collections.Generic;
using System.Data;
using System.Diagnostics;
using Lizk.DShowPlayer;

namespace SharpMedia.Pages
{
    public class LiveTVPage : MediaPage
    {
        bool seeking, resumeAfterSeek, stopped = true, started = false, showStopMenu = false;
        private int seekAmount = 0;
        private DateTime seekTimeout = DateTime.MinValue;
        private TimeSpan jumpTime = new TimeSpan(0, 1, 0), stepTime = new TimeSpan(0, 0, 15);

        private HUDVideo2 video;
        private HUDLabel labelPosition, labelDuration, labelCurrentFile, clock, lblStopPrev, lblStopNext, lblStopPlay, lblStopStop, lblError;
        private HUDImage imgChannel;
        private HUDImage background, bottomBarBackground, subSeekbar, stopMenuBack, imgStopNext, imgStopPrev, imgStopStop, imgStopPlay;
        private HUDContainerSimple bottomBar, seekBarContainer, seekBar, stopMenu;

        TvSettings tuner;

        public LiveTVPage(MediaPage parent, RectangleS selectBounds, TvSettings tuner)
            : base(parent)
        {
            this.tuner = tuner;
            InitializeComponents(selectBounds);

        }

        private void InitializeComponents(RectangleS selectBounds)
        {
            background = new HUDImage("white.png");
            background.ConstrainProportions = false;
            background.Color = Lizk.SimpleHUD.ColorS.Black;
            background.Bounds = Bounds;
            background.Alpha = 0;
            background.Anchor = Anchor.All;
            Add(background);

            video = new HUDVideo2(@"\\tv\0");
            video.Tag = tuner;
            video.Bounds = Bounds;
            video.Anchor = Anchor.All;
            video.Alpha = 1;
            video.StateChange += new EventHandler(video_StateChange);
            video.TrackChange += new EventHandler(video_TrackChange);
            Add(video);





            bottomBar = new HUDContainerSimple();
            bottomBar.Bounds = new RectangleS(0, Bounds.Height, Bounds.Width, 80);
            bottomBar.Destination = new PointS(0, Bounds.Height - 80);
            bottomBar.Anchor = Anchor.All ^ Anchor.Top;
            bottomBar.Alpha = 255;
            Add(bottomBar);

            bottomBarBackground = new HUDImage("white.png");
            bottomBarBackground.Color = Lizk.SimpleHUD.ColorS.Black;
            bottomBarBackground.Alpha = 127;
            bottomBarBackground.Anchor = Anchor.All;
            bottomBarBackground.ConstrainProportions = false;
            bottomBarBackground.Size = bottomBar.Size;
            bottomBar.Add(bottomBarBackground);

            imgChannel = new HUDImage("pb_livetv_chanbutton64.png");
            imgChannel.Bounds = new RectangleS(30, 8, 64, 64);
            imgChannel.Anchor = Anchor.Bottom | Anchor.Left;
            imgChannel.Alpha = 255;
            bottomBar.Add(imgChannel);

            


            seekBarContainer = new HUDContainerSimple();
            seekBarContainer.Bounds = new RectangleS(imgChannel.Bounds.Right + 20, 40, bottomBar.Bounds.Width - imgChannel.Bounds.Right - 357, 27);
            seekBarContainer.Anchor = Anchor.Left | Anchor.Right | Anchor.Bottom;
            seekBarContainer.Alpha = 255;
            //bottomBar.Add(seekBarContainer);

            seekBar = new HUDContainerSimple();
            seekBar.Anchor = Anchor.Left | Anchor.Right | Anchor.Bottom;
            seekBar.Bounds = new RectangleS(2, 2, 0, 23);
            seekBarContainer.Add(seekBar);

            subSeekbar = new HUDImage("pb_seekbar.png");
            subSeekbar.ConstrainProportions = false;
            subSeekbar.Anchor = Anchor.Left | Anchor.Right | Anchor.Bottom;
            subSeekbar.Size = seekBar.Size;
            seekBar.Add(subSeekbar);

            //seekbar marker
            HUDImage seekBarTop = new HUDImage("white.png");
            seekBarTop.Anchor = Anchor.Top | Anchor.Right;
            seekBarTop.Alpha = 153;
            seekBarTop.ConstrainProportions = false;
            seekBarTop.Bounds = new RectangleS(seekBar.Size.Width - 1, 0, 1, subSeekbar.Bounds.Height);
            seekBar.Add(seekBarTop);

            // seekbar top
            seekBarTop = new HUDImage("white.png");
            seekBarTop.Anchor = Anchor.All ^ Anchor.Top;
            seekBarTop.ConstrainProportions = false;
            seekBarTop.Bounds = new RectangleS(0, 0, seekBarContainer.Bounds.Width, 1);
            seekBarContainer.Add(seekBarTop);

            // bottom bar
            seekBarTop = new HUDImage("white.png");
            seekBarTop.Anchor = Anchor.All ^ Anchor.Top;
            seekBarTop.ConstrainProportions = false;
            seekBarTop.Bounds = new RectangleS(0, seekBarContainer.Bounds.Height - 1, seekBarContainer.Bounds.Width, 1);
            seekBarContainer.Add(seekBarTop);

            // left bar
            seekBarTop = new HUDImage("white.png");
            seekBarTop.Anchor = Anchor.Left ^ Anchor.Top;
            seekBarTop.ConstrainProportions = false;
            seekBarTop.Bounds = new RectangleS(0, 1, 1, seekBarContainer.Bounds.Height - 2);
            seekBarContainer.Add(seekBarTop);

            // right bar
            seekBarTop = new HUDImage("white.png");
            seekBarTop.Anchor = Anchor.Right | Anchor.Top;
            seekBarTop.ConstrainProportions = false;
            seekBarTop.Bounds = new RectangleS(seekBarContainer.Bounds.Width - 1, 0, 1, seekBarContainer.Bounds.Height - 2);
            seekBarContainer.Add(seekBarTop);

            labelCurrentFile = new HUDLabel("", "tahoma38b");
            labelCurrentFile.Color = Lizk.SimpleHUD.ColorS.White;
            labelCurrentFile.Alignment = Alignment.VCenter | Alignment.Left;
            labelCurrentFile.Anchor = Anchor.Left | Anchor.Top | Anchor.Right;
            labelCurrentFile.Bounds = new RectangleS(imgChannel.Bounds.Right + 10, imgChannel.Bounds.Top, bottomBar.Bounds.Width - imgChannel.Bounds.Right -10, imgChannel.Bounds.Height);
            bottomBar.Add(labelCurrentFile);

            labelPosition = new HUDLabel("00:00", "verdana38b");
            labelPosition.Color = Lizk.SimpleHUD.ColorS.White;
            labelPosition.Alignment = Alignment.VCenter | Alignment.Right;
            labelPosition.Anchor = Anchor.All ^ Anchor.Top;
            labelPosition.Bounds = new RectangleS(3, 1, 60, 24);
            seekBarContainer.Add(labelPosition);

            labelDuration = new HUDLabel("", "tahoma38b");
            labelDuration.Color = Lizk.SimpleHUD.ColorS.White;
            labelDuration.Anchor = Anchor.Bottom | Anchor.Left;
            labelDuration.Alignment = Alignment.VCenter | Alignment.Center;
            labelDuration.Bounds = imgChannel.Bounds;
            bottomBar.Add(labelDuration);

            clock = new HUDLabel("00:00", "tahoma50b");
            clock.Color = ColorS.White;
            clock.Anchor = Anchor.Right | Anchor.Top;
            clock.Alignment = Alignment.Center | Alignment.VCenter;
            clock.Bounds = new RectangleS(bottomBar.Bounds.Width - 160, 3, 160, 80);
            bottomBar.Add(clock);

            stopMenu = new HUDContainerSimple();
            stopMenu.Size = Size;
            stopMenu.Alpha = 0;
            stopMenu.Anchor = Anchor.All;
            Add(stopMenu);

            stopMenuBack = new HUDImage("white.png");
            stopMenuBack.ConstrainProportions = false;
            stopMenuBack.Color = Lizk.SimpleHUD.ColorS.Black;
            stopMenuBack.Bounds = Bounds;
            stopMenuBack.Alpha = 127;
            stopMenuBack.Anchor = Anchor.All;
            stopMenu.Add(stopMenuBack);

            imgStopPrev = new HUDImage("pb_previous140.png");
            imgStopPrev.Size = new SizeS(140, 140);
            stopMenu.Add(imgStopPrev);

            imgStopPlay = new HUDImage("pb_play140.png");
            imgStopPlay.Size = new SizeS(140, 140);
            stopMenu.Add(imgStopPlay);

            imgStopStop = new HUDImage("pb_stop140.png");
            imgStopStop.Size = new SizeS(140, 140);
            stopMenu.Add(imgStopStop);

            imgStopNext = new HUDImage("pb_next140.png");
            imgStopNext.Size = new SizeS(140, 140);
            stopMenu.Add(imgStopNext);

            lblStopNext = new HUDLabel("Next episode", "tahoma38b");
            lblStopNext.Size = new SizeS(220, 50);
            lblStopNext.Alignment = Alignment.Center | Alignment.Top;
            stopMenu.Add(lblStopNext);

            lblStopPlay = new HUDLabel("Resume episode", "tahoma38b");
            lblStopPlay.Size = new SizeS(220, 50);
            lblStopPlay.Alignment = Alignment.Center | Alignment.Top;
            stopMenu.Add(lblStopPlay);

            lblStopPrev = new HUDLabel("Previous episode", "tahoma38b");
            lblStopPrev.Size = new SizeS(320, 50);
            lblStopPrev.Alignment = Alignment.Center | Alignment.Top;
            stopMenu.Add(lblStopPrev);

            lblStopStop = new HUDLabel("Return to menu", "tahoma38b");
            lblStopStop.Size = new SizeS(320, 50);
            lblStopStop.Alignment = Alignment.Center | Alignment.Top;
            stopMenu.Add(lblStopStop);

            lblError = new HUDLabel("There is no Spoon", "tahoma50b");
            lblError.Alignment = Alignment.Center | Alignment.VCenter;
            lblError.Bounds = Bounds;
            lblError.Alpha = 0;
            Add(lblError);
        }

        void video_TrackChange(object sender, EventArgs e)
        {
            labelDuration.Text = "" + (video.CurrentChannel + 1);
            if (video.Channels.Count > 0)
                labelCurrentFile.Text = video.Channels[video.CurrentChannel].name;
        }

        private int GetDigits(int i)
        {
            int ret = 0;
            while (i > 0)
            {
                i /= 10;
                ret++;
            }
            if (ret == 0)
                ret = 1;
            return ret;
        }
        private void SetStopMenuPos()
        {
            imgStopPlay.Location = new PointS(Bounds.Width / 2f - 70, Bounds.Height /2f - 175);
            lblStopPlay.Location = new PointS(imgStopPlay.Bounds.Left - 40, imgStopPlay.Bounds.Bottom + 10);
            imgStopPrev.Location = new PointS(imgStopPlay.Bounds.Left - 320, imgStopPlay.Bounds.Top);
            lblStopPrev.Location = new PointS(imgStopPrev.Bounds.Left - 90, imgStopPrev.Bounds.Bottom + 10);
            imgStopNext.Location = new PointS(imgStopPlay.Bounds.Left + 320, imgStopPlay.Bounds.Top);
            lblStopNext.Location = new PointS(imgStopNext.Bounds.Left - 40, imgStopNext.Bounds.Bottom + 10);
            imgStopStop.Location = new PointS(imgStopPlay.Bounds.Left, imgStopPlay.Bounds.Bottom + 70);
            lblStopStop.Location = new PointS(imgStopStop.Bounds.Left - 90, imgStopStop.Bounds.Bottom + 10);
        }

        public override void ResizeMove(RectangleS oldRect, RectangleS newRect)
        {
            if (imgStopPlay != null)
            {
                SetStopMenuPos();
            }
            base.ResizeMove(oldRect, newRect);
        }

        void video_StateChange(object sender, EventArgs e)
        {
            if (!seeking)
            switch (video.State)
            {
                case HUDVideo2.PlayerState.Error:
                    lblError.Fade(255, 6f);
                    break;
                case HUDVideo2.PlayerState.NotLoaded:
                case HUDVideo2.PlayerState.Stopped:
                    break;
                case HUDVideo2.PlayerState.Playing:
                    started = true;
                    labelDuration.Text = "" + (video.CurrentChannel + 1);
                    if(video.Channels.Count > 0)
                        labelCurrentFile.Text = video.Channels[video.CurrentChannel].name;
                    break;
                case HUDVideo2.PlayerState.Paused:
                    break;
                case HUDVideo2.PlayerState.Menu:
                    break;
                default:
                    break;
            }
        }

        private string FormatTime(TimeSpan ts)
        {
            string deString = string.Format("{0}:{1}", ts.Minutes.ToString().PadLeft(2, '0'), ts.Seconds.ToString().PadLeft(2, '0')); ;
            if (ts.Hours > 0)
            {
                deString = ts.Hours.ToString() + ":" + deString;
            }
            return deString;
        }

        public override void Update(TimeSpan ts)
        {
            clock.Text = DateTime.Now.ToString("t");


            if (!stopped && started && video.Duration.TotalMilliseconds - video.Position.TotalMilliseconds < 100 && video.Duration.Ticks > 0)
            {
                stopped = true;
                base.Update(ts);
                return;
            }
            
            // If done fading background to max alpha and vsync is OK then we can start. 
            if (video.State == HUDVideo2.PlayerState.Stopped && background.Alpha == 255 && !started)
            {
                video.Fade(255, 2f);
                video.Play();
                stopped = false;
                seekTimeout = DateTime.Now;
            }




            // If seeking and the timeout is over.
            if (seekTimeout != DateTime.MinValue && DateTime.Now.Subtract(seekTimeout).TotalMilliseconds > 500)
            {
                if (seeking)
                {
                    video.CurrentChannel += seekAmount;
                    seekAmount = 0;
                    seeking = false;
                }
                else if (DateTime.Now.Subtract(seekTimeout).TotalMilliseconds > 2500)
                {
                    seekTimeout = DateTime.MinValue;
                    bottomBar.Destination = new PointS(0, Bounds.Height);

                }
            }

            // Update position and duration text if seeking or playing
            /*if (video.Duration.Ticks > 0 && (seeking || video.State == HUDVideo2.PlayerState.Playing))
            {
                seekBar.Size = new SizeS((float)(video.Position + seekAmount).Ticks / (float)video.Duration.Ticks * (float)seekBarContainer.Bounds.Width - 4, 23);

                labelPosition.Text = FormatTime(video.Position + seekAmount);
                labelPosition.Size = labelPosition.Text.Length > 5 ? new SizeS(93, labelPosition.Size.Height) : new SizeS(60, labelPosition.Size.Height);
                labelPosition.Location = seekBar.Bounds.Width < labelPosition.Bounds.Width ? new PointS(3, 1) : new PointS(seekBar.Bounds.Right - labelPosition.Bounds.Width, 1);
                labelDuration.Text = FormatTime(video.Duration);
            } */
            base.Update(ts);
        }

        public override void Show()
        {
            //SharpMedia.Engine.VSync = true;
            video.Load();
            background.Fade(255, 1.5f);
            Alpha = 255;
            base.Show();
        }


        public void ChangeChannel(int offset)
        {
            if (showStopMenu || !started)
                return;

            seekAmount = seekAmount + offset;

            int endChan = video.CurrentChannel + seekAmount;
            if (endChan < 0)
            {
                endChan %= video.Channels.Count;
                endChan = video.Channels.Count + endChan;
            } else if (endChan >= video.Channels.Count)
                endChan %= video.Channels.Count;

                seekAmount = endChan - video.CurrentChannel;

                labelDuration.Text = "" + (video.CurrentChannel + seekAmount + 1);
                if (video.Channels.Count > 0)
                    labelCurrentFile.Text = video.Channels[video.CurrentChannel + seekAmount].name;


            if (seekTimeout == DateTime.MinValue)
                bottomBar.Destination = new PointS(0, Bounds.Height - 80);
            seekTimeout = DateTime.Now;
            seeking = true;
        }

        private enum Zoom
        {
            Normal,
            Stretch,
            FullscreenToWidescreen
        }
        private Zoom currentZoom = Zoom.Normal;

        public override void Command(HUDCommands command, object tag)
        {
            switch (command)
            {
                case HUDCommands.Previous:
                case HUDCommands.Up:
                case HUDCommands.Rewind:
                case HUDCommands.PageUp:
                case HUDCommands.Left:
                    ChangeChannel(-1);
                    break;
                case HUDCommands.PageDown:
                case HUDCommands.Next:
                case HUDCommands.Down:
                case HUDCommands.Forward:
                case HUDCommands.Right:
                    ChangeChannel(1);
                    break;
                case HUDCommands.Select:
                    if (showStopMenu)
                        break;
                    if (seekTimeout == DateTime.MinValue)
                    {
                        bottomBar.Destination = new PointS(0, Bounds.Height - 80);
                        seekTimeout = DateTime.Now;
                    }
                    else
                    {
                        bottomBar.Destination = new PointS(0, Bounds.Height);
                        seekTimeout = DateTime.MinValue;
                    }
                    break;
                case HUDCommands.Back:
                    StopAndGoBack();
                    break;
                case HUDCommands.Fullscreen:
                    break;
                case HUDCommands.UpdateDatabase:
                    break;
                case HUDCommands.Web:
                    break;
                case HUDCommands.Preset1:
                    break;
                case HUDCommands.Preset2:
                    break;
                case HUDCommands.Preset3:
                    break;
                case HUDCommands.Menu:
                    switch (currentZoom)
                    {
                        case Zoom.Normal:
                            currentZoom = Zoom.Stretch;
                            video.ConstrainProportions = false;
                            break;
                        case Zoom.Stretch:
                            currentZoom = Zoom.FullscreenToWidescreen;
                            video.ConstrainProportions = false;
                            RectangleS r = HUDImage.ResizeConstrained(true, new SizeS(4, 3), Bounds.Size);
                            SizeS dsage = new SizeS(Bounds.Width, Bounds.Height * Bounds.Width / r.Width);
                            PointS pso = new PointS(0, -(dsage.Height - Bounds.Height) / 2);
                            video.Bounds = new RectangleS(pso, dsage);
                            break;
                        case Zoom.FullscreenToWidescreen:
                            video.Bounds = Bounds;
                            currentZoom = Zoom.Normal;
                            video.ConstrainProportions = true;
                            break;
                    }
                    break;
                case HUDCommands.Play:
                case HUDCommands.Pause:
                case HUDCommands.PlayPause:
                    if (showStopMenu)
                    {
                        showStopMenu = false;
                        stopMenu.Fade(0, 6f);
                        // When restarting using stopMenu
                        if (stopped)
                        {

                            video.Seek(TimeSpan.Zero, true);
                            stopped = false;
                            started = false;
                            break;
                        }
                    }
                    if (seeking)
                        {
                            resumeAfterSeek = !resumeAfterSeek;
                            break;
                        }
                        if (video.State == HUDVideo2.PlayerState.Playing)
                        {
                            video.Pause();
                            bottomBar.Destination = new PointS(0, Bounds.Height - 80);
                            seekTimeout = DateTime.MinValue;
                        }
                        else if (video.State == HUDVideo2.PlayerState.Paused || video.State == HUDVideo2.PlayerState.Stopped)
                        {
                            video.Play();
                            seekTimeout = DateTime.Now;
                        }
                    break;
                case HUDCommands.Stop:
                        StopAndGoBack();
                    break;
                default:
                    if (parent != null)
                        parent.Command(command, tag);
                    break;
            }
        }

        private void StopAndGoBack()
        {
            stopMenu.Alpha = 0;
            video.Stop();
            //SharpMedia.Engine.VSync = false;
            Fade(0, 2f);
            video.Alpha = 0;
            SharpMedia.Back();
        }

    }
}